package me.zhengjie.modules.sync.pull.v20;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiaofang.applet.common.exception.BusinessException;
import com.qiaofang.core.gatewayclient.GatewayTemplate;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.quartz.service.dto.SyncCommon;
import me.zhengjie.modules.sync.PullBase;
import me.zhengjie.modules.sync.request.PullResourceUuidListDetailDTO;
import me.zhengjie.modules.sync.request.PullResourceUuidListRequest;
import me.zhengjie.modules.sync.response.PullResourceUuidListDTO;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static me.zhengjie.modules.quartz.service.constants.SyncConstants.ON;
import static me.zhengjie.modules.quartz.service.constants.SyncConstants.V20_PULL_RESOURCE_UUID_LIST_API;

/**
 * @author QF2019
 */
@Slf4j
public abstract class MarketingPullBase extends PullBase {

    @Value("${spring.profiles.active}")
    protected String active;

    @Autowired
    private GatewayTemplate gatewayTemplate;

    @Override
    public void pull(SyncCommon syncCommon, Date dynamicDate) {

        super.syncCommon = syncCommon;
        super.dynamicDate = dynamicDate;


        PullResourceUuidListDetailDTO dto = getPullResourceUuidListDetailDto(dynamicDate);
        PullResourceUuidListRequest request = PullResourceUuidListRequest.builder()
                .resourceType(getResourceType()).dto(dto).build();
        PullResourceUuidListDTO resourceUuidListDTO;
        while (true){
            // 1、分页拉取资源UuidList
            resourceUuidListDTO = doRequestResourceUuidList(request);
            if(resourceUuidListDTO.getListSize() == 0) {
                break;
            }

            // 已删除的业务数据uuid
            List<String> delUuids = resourceUuidListDTO.getList().stream()
                    .filter(item -> item.getResourceDeleted())
                    .map(item -> item.getResourceUUid()).collect(Collectors.toList());
            // 未删除的业务数据uuid
            List<String> uuids = resourceUuidListDTO.getList().stream()
                    .filter(item -> !item.getResourceDeleted())
                    .map(item -> item.getResourceUUid()).collect(Collectors.toList());

            // 2、删除uuid标记是已删除的业务数据
            removeBusinessData(delUuids);

            // 3、根据uuid批量获取业务数据
            save(doRequest(uuids));
            dto.setScrollId(resourceUuidListDTO.getScrollId());
        }
    }

    /**
     * 获取资源类型
     * @return
     */
    public abstract String getResourceType();

    /**
     * 删除业务数据
     * @param uuids
     */
    public abstract void removeBusinessData(List<String> uuids);

    /**
     * 请求业务接口
     * @param request
     * @return
     */
    private PullResourceUuidListDTO doRequestResourceUuidList(PullResourceUuidListRequest request) {
        HttpHeaders headers = getHeaders();
        log.info("sync request {},header {}", request, headers);

        JSONObject result;
        try {
            result = gatewayTemplate.postForObject(V20_PULL_RESOURCE_UUID_LIST_API, request, headers, JSONObject.class);
            log.info("sync result {}", result);
            String responseCode = result.getString("responseCode");
            if(!StringUtils.equals(ON, responseCode)) {
                log.error("sync fail,result:{}", result);
                throw new BusinessException(result.getString("responseMessage"));
            }
            return result.getJSONObject("data").toJavaObject(PullResourceUuidListDTO.class);
        } catch (Exception e) {
            log.error("sync error", e);
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 查询业务数据
     * @param uuids
     * @return
     */
    private JSONArray doRequest(List<String> uuids) {
        if(CollectionUtils.isEmpty(uuids)) {
            return null;
        }

        HttpHeaders headers = getHeaders();
        log.info("sync params {},header {}", uuids, headers);
        JSONObject param = new JSONObject();
        param.put("uuids", uuids);
        JSONObject result;
        try {
            result = gatewayTemplate.postForObject(getApiUrl(), param, headers, JSONObject.class);
            log.info("sync result {}", result);
            String responseCode = result.getString("responseCode");
            if(!StringUtils.equals(ON, responseCode)) {
                syncDataLogSave(param, responseCode, result.getString("responseMessage"));
                return null;
            }
            return result.getJSONArray("data");
        } catch (Exception e) {
            log.error("sync error", e);
            syncDataLogSave(param, "-9999", e.getMessage());
            return null;
        }
    }

    /**
     * 获取请求营销系统接口的请求头
     * @return
     */
    private HttpHeaders getHeaders() {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("companyUuid", syncCommon.getCompanyUuid());
        return headers;    }

    /**
     * 获取查询uuidList的请求参数
     * @return
     */
    private PullResourceUuidListDetailDTO getPullResourceUuidListDetailDto(Date dynamicDate) {
        PullResourceUuidListDetailDTO dto = PullResourceUuidListDetailDTO.builder()
                .windowSize(pageSize).useAsc(true).build();
        // 判断是否进行全量同步，全量同步不传起始、截止时间
        if (syncCommon.getInit()) {
            return dto;
        } else if ("dev".equals(active) || "test".equals(active)){
            //dev test环境同步当天的
            LocalDate now = LocalDate.now();
            Date startTime = Date.from(LocalDateTime.of(now, LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant());
            Date endTime = Date.from(LocalDateTime.of(now.plusDays(1), LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant());
            // 如果传入了起止时间则同步起始时间至当天0点以前的数据
            if(dynamicDate != null) {
                startTime = dynamicDate;
            }
            dto.setStartUpdatedTime(startTime);
            dto.setEndUpdatedTime(endTime);
            return dto;
        }

        // 增量同步只同步前一天的数据(00:00:00~23:59:59)
        LocalDate now = LocalDate.now();
        Date startTime = Date.from(LocalDateTime.of(now.plusDays(-1), LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant());
        Date endTime = Date.from(LocalDateTime.of(now, LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant());
        // 如果传入了起止时间则同步起始时间至当天0点以前的数据
        if(dynamicDate != null) {
            startTime = dynamicDate;
        }
        dto.setStartUpdatedTime(startTime);
        dto.setEndUpdatedTime(endTime);
        return dto;
    }
}
